/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.common.base.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.constants.ConstantVars;
import com.je.common.base.constants.tree.NodeType;
import com.je.common.base.constants.workflow.AudFlagStatus;
import com.je.common.base.db.JEDatabase;
import com.je.common.base.document.FileCopyDTO;
import com.je.common.base.entity.func.FuncInfo;
import com.je.common.base.entity.func.FuncRelation;
import com.je.common.base.entity.func.FuncRelationField;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.mapper.query.Query;
import com.je.common.base.mvc.BaseMethodArgument;
import com.je.common.base.service.*;
import com.je.common.base.service.db.PcDBMethodServiceFactory;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.service.rpc.FunInfoRpcService;
import com.je.common.base.util.*;
import com.je.core.entity.extjs.JSONTreeNode;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.sql.Clob;
import java.util.*;

@Service
public class CommonServiceImpl extends AbstractCommonService implements CommonService {

    /**
     * 基础数据操作封装
     */
    @Autowired
    private MetaService metaService;
    @Autowired
    private MetaResourceService metaResourceService;
    /**
     * 文件操作service
     */
    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;
    @Autowired
    private FunInfoRpcService funInfoRpcService;
    @Autowired
    protected PlatformService manager;
    @Autowired
    private BeanService beanService;
    @Autowired
    private QueryBuilderService queryBuilderService;
    @Resource(name = "taskExecutor")
    private TaskExecutor taskExecutor;

    @Override
    public List<Map<String, Object>> loadGridTree(String rootId, String tableCode, String excludes, Boolean checked, Query query) {
        DynaBean table = beanService.getResourceTable(tableCode);
        JSONTreeNode template = beanService.buildJSONTreeNodeTemplate((List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS));
        List<Map<String, Object>> datas = loadTree(rootId, template, table, excludes, checked, query);
        Map<String, Object> root = buildJSONTree4Dyna(datas, table.getStr(BeanService.KEY_PK_CODE), template.getParent());
        List<Map<String, Object>> childrens = (List<Map<String, Object>>) root.get("children");
        return childrens;
    }

    @Override
    public List<JSONTreeNode> loadTreeNodeList(String rootId, String tableName, JSONTreeNode template, Query where) {
        return loadTreeNodeList(rootId, tableName, template, where, null, null);
    }

    /**
     * 查询属性表数据(无树形结构)
     *
     * @param rootId   根节点id
     * @param template 表字段与树形字段对应关系
     * @param table    表信息
     * @param excludes
     * @param checked
     * @param query    查询信息
     * @return java.util.List
     */
    public List<Map<String, Object>> loadTree(String rootId, JSONTreeNode template, DynaBean table, String excludes, Boolean checked, Query query) {
        //资源表信息
        String tableCode = table.getStr(BeanService.KEY_TABLE_CODE);
        List<DynaBean> columns = (List<DynaBean>) table.get(BeanService.KEY_TABLE_COLUMNS);

        //字段sql
        StringBuffer filedSql = new StringBuffer();
        for (DynaBean column : columns) {
            filedSql.append(" ").append(column.getStr("TABLECOLUMN_CODE")).append(",");
        }
        filedSql.deleteCharAt(filedSql.length() - 1);
        // 拼接语句
        ConditionsWrapper select = ConditionsWrapper.builder().apply(" SELECT ").apply(filedSql.toString()).apply(" from ").apply(tableCode).apply(" WHERE ")
                //(SY_PATH LIKE '%ROOT%' + whereSql )
                .and(i -> {
                    i.like(template.getNodePath(), rootId);
                    query.buildWrapper(i);
                })
                // OR ID = 'ROOT'
                .or().eq(template.getId(), rootId);
        //order条件
        if (query != null && StringUtil.isNotEmpty(query.getFuncOrderSql())) {
            select.apply(query.getFuncOrderSql());
        } else {
            select.apply(" ORDER BY ").apply(template.getParent()).apply(" asc");
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                select.apply(", ").apply(template.getOrderIndex()).apply(" asc ");
            }
        }

        //查询数据
        List<Map<String, Object>> list = metaService.selectSql(select);
        list.forEach(item -> {
            //"id","text","cls","leaf","href","hrefTarget","expandable","description","code","icon","iconCls","bigIcon","bigIconCls","parent","nodeInfo","nodeInfoType","disabled","nodePath"
            item.put("children", new ArrayList<Map>());
            item.put("id", item.get(template.getId()));
            item.put("text", item.get(template.getText()));
            item.put("code", item.get(template.getCode()));
            item.put("parent", item.get(template.getParent()));
            if (StringUtil.isNotEmpty(template.getNodeInfo())) {
                item.put("nodeInfo", item.get(template.getNodeInfo()));
            }
            if (StringUtil.isNotEmpty(template.getNodeInfoType())) {
                item.put("nodeInfoType", item.get(template.getNodeInfoType()));
            }
            if (StringUtil.isNotEmpty(template.getNodeType())) {
                item.put("nodeType", item.get(template.getNodeType()));
            }
            if (StringUtil.isNotEmpty(template.getIcon())) {
                item.put("icon", item.get(template.getIcon()));
            }
            if (StringUtil.isNotEmpty(template.getIconColor())) {
                item.put("iconCls", item.get(template.getIconColor()));
            }
            if (StringUtil.isNotEmpty(template.getLayer())) {
                item.put("layer", item.get(template.getLayer()));
            }
            if (StringUtil.isNotEmpty(template.getDisabled())) {
                item.put("disabled", item.get(template.getDisabled()));
            }
            if (StringUtil.isNotEmpty(template.getNodePath())) {
                item.put("nodePath", item.get(template.getNodePath()));
            }
            if (StringUtil.isNotEmpty(template.getDescription())) {
                item.put("description", item.get(template.getDescription()));
            }
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                item.put("orderIndex", item.get(template.getOrderIndex()));
            }
            item.put("checked", checked);
            item.put("leaf", true);
            item.put("children", new ArrayList<HashMap>());
            for (String exclude : excludes.split(",")) {
                item.remove(exclude);
            }
            // TODO 如果是oracle则特殊处理
            if (ConstantVars.STR_ORACLE.equals(JEDatabase.getCurrentDatabase())) {
                for (Object key : item.keySet()) {
                    if (item.get(key + "") != null && item.get(key + "") instanceof Clob) {
                        item.put(key + "", StringUtil.getClobValue(item.get(key + "")));
                    }
                }
            }
        });
        return list;
    }

    @Override
    @Transactional
    public DynaBean doSave(DynaBean dynaBean) {
        String tableCode = dynaBean.getTableCode();
        if (StringUtil.isEmpty(dynaBean.getStr("SY_STATUS"))) {
            //默认为启用数据
            dynaBean.set("SY_STATUS", "1");
        }
        metaService.insert(dynaBean);

        if (StringUtil.isNotEmpty(dynaBean.getStr("SY_PATH"))) {
            String uuid = dynaBean.getStr(dynaBean.getPkCode(), "");
            if (StringUtil.isEmpty(uuid)) {
                throw new PlatformException("主键保存后未生成", PlatformExceptionEnum.UNKOWN_ERROR);
            }
            dynaBean.setStr(dynaBean.getPkCode(), uuid);
            dynaBean.set("SY_PARENTPATH", dynaBean.getStr("SY_PATH"));
            dynaBean.set("SY_PATH", dynaBean.getStr("SY_PATH") + "/" + uuid);
            if (StringUtil.isEmpty(dynaBean.getStr("SY_NODETYPE"))) {
                dynaBean.set("SY_NODETYPE", NodeType.LEAF);
            }
            DynaBean parent = metaService.selectOneByPk(dynaBean.getTableCode(), dynaBean.getStr("SY_PARENT"), dynaBean.getPkCode() + ",SY_NODETYPE,SY_TREEORDERINDEX");
            if (parent != null && NodeType.LEAF.equals(parent.getStr("SY_NODETYPE"))) {
                metaService.executeSql(ConditionsWrapper.builder(
                        " UPDATE " + tableCode + " SET SY_NODETYPE='" + NodeType.GENERAL +
                                "' where " + dynaBean.getPkCode() + " = '" + dynaBean.getStr("SY_PARENT") +
                                "' AND SY_NODETYPE!='" + NodeType.ROOT + "'"));
            }
            //构建序号
            if (dynaBean.containsKey("SY_TREEORDERINDEX") && StringUtil.isNotEmpty(dynaBean.getStr("SY_PARENT"))) {
                dynaBean.set("SY_TREEORDERINDEX", parent.getStr("SY_TREEORDERINDEX"));
                generateTreeOrderIndex(dynaBean);
            }
        }
        metaService.update(dynaBean);
        return dynaBean;
    }

    @Override
    @Transactional
    public List<DynaBean> doUpdateList(String tableCode, String updateStr, String funcType, String funcCode, String codeGenFieldInfo) {
        List<DynaBean> updateList = new ArrayList<>();
        List<DynaBean> lists = beanService.buildUpdateList(updateStr, tableCode);

        List<String> updatePkList = new ArrayList<>();
        for (DynaBean bean : lists) {
            String action = bean.getStr("__action__");
            String pkValue = bean.getPkValue();
            if (!"doInsert".equals(action) && !Strings.isNullOrEmpty(pkValue)) {
                updatePkList.add(pkValue);
            }
        }

        if (!Strings.isNullOrEmpty(funcCode) && !updatePkList.isEmpty()) {
            if (!validDynaBeanListUpdatePerm(funcCode, tableCode, ConditionsWrapper.builder().in(beanService.getPKeyFieldNamesByTableCode(tableCode), updatePkList))) {
                throw new PlatformException("您没有此数据的更改权限！", PlatformExceptionEnum.UNKOWN_ERROR);
            }
        }
        DynaBean funcInfo = metaResourceService.selectOneByNativeQuery("JE_CORE_FUNCINFO", NativeQuery.build().eq("FUNCINFO_FUNCCODE", funcCode));
        if (funcInfo != null) {
            funcType = funcInfo.getStr("FUNCINFO_FUNCTYPE");
        }
        for (DynaBean bean : lists) {
            String frontEndPkValueKey = "";
            if ("VIEW".equals(funcType) && StringUtil.isNotEmpty(funcCode)) {
                updateList.add(doViewData(funcCode, bean));
            } else {
                String action = bean.getStr("__action__");
                String pkValue = bean.getPkValue();
                if ("doInsert".equals(action) || StringUtil.isEmpty(pkValue)) {
                    buildModelCreateInfo(bean);
                    if (StringUtil.isNotEmpty(codeGenFieldInfo)) {
                        buildCode(codeGenFieldInfo, bean);
                    }
                    //默认为启用数据
                    bean.set("SY_STATUS", "1");
                    frontEndPkValueKey = getModelCreateListInsertId(bean);
                    metaService.insert(bean);
                } else {
                    buildModelModifyInfo(bean);
                    metaService.update(bean);
                }
                DynaBean dynaBean = metaService.selectOneByPk(bean.getTableCode(), bean.getPkValue());
                if (!Strings.isNullOrEmpty(frontEndPkValueKey)) {
                    dynaBean.setStr(FRONT_END_PK_VALUE_KEY, frontEndPkValueKey);
                }
                updateList.add(dynaBean);
            }
        }
        return updateList;
    }

    @Override
    @Transactional
    @Deprecated
    public int doUpdateAllList(String tableCode, String funcType, String funcCode, Map<String, Object> values, BaseMethodArgument param, HttpServletRequest request) {
        DynaBean funcInfo = metaResourceService.selectOne("JE_CORE_FUNCINFO",
                NativeQuery.build().eq("FUNCINFO_FUNCCODE", funcCode), "FUNCINFO_VIEWCONFIGINFO,FUNCINFO_FUNCTYPE,FUNCINFO_TABLENAME,JE_CORE_FUNCINFO_ID");
        funcType = funcInfo.getStr("FUNCINFO_FUNCTYPE");
        String viewConfigInfo = funcInfo.getStr("FUNCINFO_VIEWCONFIGINFO");
        if ("view".equals(funcType) && !(StringUtils.isBlank(viewConfigInfo) || "[]".equals(viewConfigInfo))) {
            //如果配置为空，只修改当前表数据
            String funcId = funcInfo.getStr("JE_CORE_FUNCINFO_ID");
            param.setTableCode(funcInfo.getStr("FUNCINFO_TABLENAME"));
            param.setFuncId(funcId);
            ConditionsWrapper conditionsWrapper = manager.buildWrapper(param, request);
            //构建查询条件
            List<DynaBean> lists = metaService.select(funcInfo.getStr("FUNCINFO_TABLENAME"), conditionsWrapper);
            for (DynaBean bean : lists) {
                Map<String, Object> updateValues = ((DynaBean) request.getAttribute("dynaBean")).getValues();
                for (Map.Entry<String, Object> entry : updateValues.entrySet()) {
                    bean.set(entry.getKey(), entry.getValue());
                }
                doViewData(funcCode, bean, funcInfo);
            }
            return lists.size();
        } else {
            StringBuffer updateSql = new StringBuffer();
            for (Map.Entry<String, Object> entry : values.entrySet()) {
                updateSql.append("," + entry.getKey() + "='" + entry.getValue() + "'");
            }
            updateSql = new StringBuffer(updateSql.substring(1, updateSql.length()));
            int i = metaService.executeSql(String.format("UPDATE %s SET %s", tableCode, updateSql));
            return i;
        }

    }

    @Override
    @Transactional
    public List<DynaBean> doUpdateList(String tableCode, String updateStr, String funcType, String viewConfigInfo) {
        List<DynaBean> updateList = new ArrayList<>();
        List<DynaBean> lists = beanService.buildUpdateList(updateStr, tableCode);
        for (DynaBean bean : lists) {
            if ("view".equals(funcType) && StringUtil.isNotEmpty(viewConfigInfo)) {
                doViewData(viewConfigInfo, bean);
            }

            String action = bean.getStr("__action__");
            String pkValue = bean.getPkValue();
            if ("doInsert".equals(action) || StringUtil.isEmpty(pkValue)) {
                buildModelCreateInfo(bean);
                //默认为启用数据
                bean.set("SY_STATUS", "1");
                metaService.insert(bean);
            } else {
                buildModelModifyInfo(bean);
                metaService.update(bean);
            }
            updateList.add(bean);
        }
        return updateList;
    }

    @Override
    @Transactional
    public DynaBean doCopy(DynaBean dynaBean, String funcCode, String codeGenFieldInfo, String uploadableFields) {
        FuncInfo funcInfo = funInfoRpcService.getFuncInfo(funcCode);
        String tableCode = dynaBean.getTableCode();
        String pkCode = dynaBean.getPkCode();
        String oldPkValue = dynaBean.getPkValue();
        //老数据
        DynaBean oldBean = metaService.selectOneByPk(tableCode, oldPkValue);
        //新数据
        DynaBean newBean = oldBean.clone();
        //删除主键
        newBean.remove(pkCode);
        //处理编号
        if (StringUtil.isNotEmpty(codeGenFieldInfo)) {
            buildCode(codeGenFieldInfo, newBean);
        }
        //插入复制的数据生成主键
        buildModelCreateInfo(newBean);
        metaService.insert(newBean);
        //获取新主键
        String newPkValue = newBean.getPkValue();
        //如果是树形功能，修改树形字段
        if ("tree".equalsIgnoreCase(funcInfo.getFuncType())) {
            newBean.set("SY_PATH", oldBean.getStr("SY_PATH", "").replace(oldPkValue, newPkValue));
            metaService.update(newBean);
        }
        //复制附件
        if (StringUtil.isNotEmpty(uploadableFields)) {
            for (String fieldCode : uploadableFields.split(",")) {
                List<FileCopyDTO> dtos = documentInternalRpcService.copyFiles(SecurityUserHolder.getCurrentAccountRealUserId(), tableCode, oldPkValue, fieldCode, newPkValue);
                if (!dtos.isEmpty()) {
                    FileCopyDTO dto = dtos.get(0);
                    oldBean.set(fieldCode, dto.getName() + "*" + dto.getFileKey());
                }
            }
        }

        copyChild(funcInfo, newBean, oldPkValue);
        return newBean;
    }

    @Override
    @Transactional
    public DynaBean doViewData(String funcCode, DynaBean dynaBean) {
        DynaBean funcInfo = metaResourceService.selectOneByNativeQuery("JE_CORE_FUNCINFO", NativeQuery.build().eq("FUNCINFO_FUNCCODE", funcCode));
        return doViewData(funcCode, dynaBean, funcInfo);
    }

    @Override
    @Transactional
    public DynaBean doViewData(String funcCode, DynaBean dynaBean, DynaBean funcInfo) {
        String action = dynaBean.getStr("__action__");
        String viewConfigInfo = funcInfo.getStr("FUNCINFO_VIEWCONFIGINFO");
        DynaBean oldData = metaService.selectOne(dynaBean.getTableCode(), ConditionsWrapper.builder().eq(dynaBean.getPkCode(), dynaBean.getPkValue()));
        if (StringUtils.isBlank(viewConfigInfo) || "[]".equals(viewConfigInfo)) {
            dynaBean.table(funcInfo.getStr("FUNCINFO_CRUDTABLENAME"));
            String pkValue = dynaBean.getPkValue();
            if (StringUtil.isEmpty(pkValue) && oldData != null) {
                //视图子表
                DynaBean resourceTable = metaResourceService.selectOneByNativeQuery("JE_CORE_RESOURCETABLE",
                        NativeQuery.build().eq("RESOURCETABLE_TABLECODE", funcInfo.getStr("FUNCINFO_CRUDTABLENAME")));
                String pkCode = resourceTable.getStr("RESOURCETABLE_PKCODE");
                dynaBean.setStr(pkCode, oldData.getStr(pkCode));
            }
            if (StringUtils.isBlank(dynaBean.getPkValue()) || "doInsert".equals(action)) {
                throw new PlatformException("请配置【视图操作表信息】后再执行保存", PlatformExceptionEnum.UNKOWN_ERROR);
            } else {
                metaService.update(dynaBean);
            }
            return dynaBean;
        }
        JSONArray arrays = JSONArray.parseArray(viewConfigInfo);
//        if (arrays != null && arrays.size() < 2) {
//            throw new PlatformException("【视图操作表信息】包含主表和至少一个子表", PlatformExceptionEnum.UNKOWN_ERROR);
//        }

        for (int i = 0; i < arrays.size(); i++) {
            JSONObject obj = arrays.getJSONObject(i);
            String tableCode = obj.getString("tableCode");
            String pkCode = obj.getString("pkCode");
            dynaBean.set(pkCode, oldData == null ? dynaBean.getStr(pkCode) : oldData.getStr(pkCode));
            String viewPkCode = obj.getString("viewFieldCode");
            String fieldCodes = obj.getString("fieldCodes");
            String updateFlag = obj.getString("updateData");
            String insertFlag = "0";
            if (obj.containsKey("insertData")) {
//                insertFlag = "insertData";
                insertFlag = obj.getString("insertData");
            }
            String doFieldCodes = "";
            //TODO 前端应该传doFieldCodes
            if (obj.containsKey("dofieldCodes")) {
                doFieldCodes = obj.getString("dofieldCodes");
            }
            if (StringUtil.isNotEmpty(tableCode) && StringUtil.isNotEmpty(pkCode) && StringUtil.isNotEmpty(viewPkCode)
                    && StringUtil.isNotEmpty(fieldCodes)) {
                if (!dynaBean.containsKey(viewPkCode)) {
                    continue;
                }
                String pkValue = dynaBean.getStr(viewPkCode);
                DynaBean bean = new DynaBean(tableCode, true);
                for (String fieldCode : fieldCodes.split(",")) {
                    if (dynaBean.containsKey(fieldCode)) {
                        bean.set(fieldCode, dynaBean.get(fieldCode));
                        dynaBean.set(fieldCode, dynaBean.get(fieldCode));
                    }
                }
                if (StringUtil.isNotEmpty(doFieldCodes) && doFieldCodes.split(",").length > 1) {
                    String[] thisFields = doFieldCodes.split(",")[0].split("~");
                    String[] targerFields = doFieldCodes.split(",")[1].split("~");
                    for (int j = 0; j < thisFields.length; j++) {
                        if (dynaBean.containsKey(thisFields[j])) {
                            bean.set(targerFields[j], dynaBean.get(thisFields[j]));
                            dynaBean.set(targerFields[j], dynaBean.get(thisFields[j]));
                        }
                    }
                }
                if (StringUtil.isNotEmpty(pkValue) && !"doInsert".equals(action)) {
                    if ("1".equals(updateFlag)) {
                        bean.set(pkCode, pkValue);
                        dynaBean.set(pkCode, pkValue);
                        metaService.update(bean);
                    }
                } else if ((StringUtil.isEmpty(pkValue) || "doInsert".equals(action)) && "1".equals(insertFlag)) {
                    buildModelCreateInfo(bean);
                    metaService.insert(bean);
                    //第一条才是主表的配置
                    if (i == 0) {
                        dynaBean.setStr(FRONT_END_PK_VALUE_KEY, getModelCreateListInsertId(dynaBean));
                    }
                    dynaBean.set(viewPkCode, bean.getStr(pkCode));
                }

            }
        }
        dynaBean = metaService.selectOneByPk(funcInfo.getStr("FUNCINFO_TABLENAME"), dynaBean.getPkValue());
        return dynaBean;
    }

    private void copyChild(FuncInfo funcInfo, DynaBean dynaBean, String oldPkValue) {
        String pkName = dynaBean.getStr(BeanService.KEY_PK_CODE);
        List<FuncRelation> childrens = funcInfo.getChildren();
        for (FuncRelation children : childrens) {
            //不勾选级联复制 或者 类型为自定义 --> 则不复制
            if (!children.getCopyChild() || !ArrayUtils.contains(new String[]{"func", "tree", "childfuncfield"}, children.getType())) {
                continue;
            }
            List<FuncRelationField> relatedFields = children.getChildFields();
            String childTableCode = children.getTableCode();
            String foreignKey = beanService.getForeignKeyField(childTableCode, dynaBean.getTableCode(), pkName, relatedFields);
            //如果未找到外键不复制
            if (StringUtil.isEmpty(foreignKey)) {
                continue;
            }
            String funcCode = children.getCode();
            FuncInfo childFunInfo = funInfoRpcService.getFuncInfo(funcCode);
            if (childFunInfo != null) {
                List<FuncRelation> childChildrens = childFunInfo.getChildren();
                DynaBean childTable = beanService.getResourceTable(childTableCode);
                String childPkCode = beanService.getPKeyFieldNames(childTable);
                //如果子功能还含有子功能，则一条一条复制数据
                if ((childChildrens != null && childChildrens.size() > 0) || "tree".equals(children.getType())) {
                    //树形表的复制
                    List<DynaBean> childDatas = metaService.select(childTableCode, ConditionsWrapper.builder().eq(foreignKey, oldPkValue).apply(childFunInfo.getWhereSql()));
                    Map<String, String> pkMap = new HashMap<String, String>();
                    for (DynaBean childData : childDatas) {
                        String oldChildPkValue = childData.getStr(childPkCode);
                        childData.set(BeanService.KEY_TABLE_CODE, childTableCode);
                        //主键设空
                        childData.set(childPkCode, null);
                        //设置新的外键
                        childData.set(foreignKey, dynaBean.getStr(pkName));
                        buildModelCreateInfo(childData);
                        metaService.insert(childData);
                        pkMap.put(oldChildPkValue, childData.getStr(childPkCode));
                        childData.set(BeanService.KEY_TABLE_CODE, childTableCode);
                        if (childChildrens != null && childChildrens.size() > 0) {
                            copyChild(childFunInfo, childData, oldChildPkValue);
                        }
                    }
                    //如果是树形功能则替换父节点及路径 父节点路径
                    if ("tree".equals(children.getType())) {
                        for (Map.Entry<String, String> entry : pkMap.entrySet()) {
                            metaService.executeSql(ConditionsWrapper.builder(
                                    "UPDATE " + childTableCode +
                                            " SET SY_PARENT=REPLACE(SY_PARENT,'" + entry.getKey() + "','" + entry.getValue() + "')," +
                                            " SY_PARENTPATH=REPLACE(SY_PARENTPATH,'" + entry.getKey() + "','" + entry.getValue() + "')," +
                                            " SY_PATH=REPLACE(SY_PATH,'" + entry.getKey() + "','" + entry.getValue() + "') WHERE " + foreignKey + "=" + "'" + dynaBean.getStr(pkName) + "'"));
                        }
                    }
                } else {
                    String createTime = DateUtils.formatDateTime(new Date());
                    String queryColumns = beanService.getFieldNames(childTable, new String[]{childPkCode, foreignKey, "SY_CREATETIME", "SY_CREATEORGID", "SY_CREATEORGNAME", "SY_CREATEUSERID", "SY_CREATEUSERNAME", "SY_AUDFLAG", "SY_PDID", "SY_PIID"});
                    StringBuffer insertSql = new StringBuffer();
                    String uuidStr = PcDBMethodServiceFactory.getPcDBMethodService().getGenerateUUID();
                    insertSql.append(" INSERT INTO  " + childTableCode + " (" + childPkCode + "," + foreignKey + "," + queryColumns + ",SY_CREATETIME,SY_CREATEORGID,SY_CREATEORGNAME,SY_CREATEUSERID,SY_CREATEUSERNAME,SY_AUDFLAG,SY_PDID,SY_PIID) ");
                    insertSql.append("SELECT " + uuidStr + ",'" + dynaBean.getStr(pkName) + "'," + queryColumns + ",'" + createTime + "','" + SecurityUserHolder.getCurrentAccountRealOrgId() + "','" + SecurityUserHolder.getCurrentAccountRealOrgName() + "','" + SecurityUserHolder.getCurrentAccountRealUserId() + "','" + SecurityUserHolder.getCurrentAccountRealUserName() + "','" + AudFlagStatus.NOSTATUS + "','','' FROM " + childTableCode + " WHERE " + foreignKey + "='" + oldPkValue + "' " + childFunInfo.getWhereSql());
                    metaService.executeSql(ConditionsWrapper.builder(insertSql.toString()).table(childTableCode));
                }
            }
        }
    }

    @Override
    @Transactional
    public void removeChild(String funcCode, String tableCode, String pkCode, String ids, boolean doTree) {
        //级联删除子功能
        if (StringUtil.isNotEmpty(funcCode)) {
            FuncInfo funcInfo = funInfoRpcService.getFuncInfo(funcCode);
            if (decideDeleteChildren(funcInfo)) {
                //封装条件
                ConditionsWrapper wrapper = ConditionsWrapper.builder();
                if (doTree) {
                    for (String id : ids.split(",")) {
                        wrapper.or().like("SY_PATH", id);
                    }
                }
                wrapper.in(pkCode, ids.split(","));
                List<DynaBean> lists = metaService.select(tableCode, wrapper);
                for (DynaBean bean : lists) {
                    removeChildData(bean, funcInfo);
                }
            }
        }
    }

    @Transactional
    public void removeChildData(DynaBean dynaBean, FuncInfo funcInfo) {
        List<FuncRelation> childrens = funcInfo.getChildren();
        for (FuncRelation children : childrens) {
            if (!ArrayUtils.contains(new String[]{"func", "tree", "childfuncfield"}, children.getType())) {
                continue;
            }
            String childTableCode = children.getTableCode();
            List<FuncRelationField> relatedFields = children.getChildFields();
            List<FuncRelationField> delRelatedFields = new ArrayList<>();
            //遍历主子关联字段
            for (FuncRelationField childField : relatedFields) {
                //找到需要级联删除的字段
                if (childField.getDeleteChild()) {
                    delRelatedFields.add(childField);
                }
            }
            if (delRelatedFields.size() == 0) {
                continue;
            }
            //构建主子SQL 并查询出子数据
            String childSql = funInfoRpcService.buildWhereSql4funcRelation(delRelatedFields, dynaBean);
            List<DynaBean> lists = metaService.select(childTableCode, ConditionsWrapper.builder().apply(queryBuilderService.trimSql(childSql)));
            if (lists.size() == 0) {
                continue;
            }

            String funcCode = children.getCode();
            FuncInfo childFunInfo = funInfoRpcService.getFuncInfo(funcCode);
            if (childFunInfo != null) {
                String childPkCode = childFunInfo.getPkCode();
                for (DynaBean childBean : lists) {
                    removeChildData(childBean, childFunInfo);
                }
                metaService.executeSql(ConditionsWrapper.builder(" DELETE FROM " + childTableCode +
                        " WHERE " + childPkCode + " IN (" + StringUtil.buildArrayToString(ArrayUtils.getBeanFieldArray(lists, childPkCode)) + ")")
                );
            }
        }
    }

    @Override
    @Transactional
    public int doViewDelData(String viewConfigInfo, String viewTableCode, String mainPkCode, String ids) {
        JSONArray arrays = JSONArray.parseArray(viewConfigInfo);
//        if (arrays != null && arrays.size() < 2) {
//            throw new PlatformException("【视图操作表信息】包含主表和至少一个子表！", PlatformExceptionEnum.UNKOWN_ERROR);
//        }
        List<DynaBean> lists = metaService.select(viewTableCode, ConditionsWrapper.builder().in(mainPkCode, ids.split(",")));
        for (int i = 0; i < arrays.size(); i++) {
            JSONObject obj = arrays.getJSONObject(i);
            String tableCode = obj.getString("tableCode");
            String pkCode = obj.getString("pkCode");
            String viewPkCode = obj.getString("viewFieldCode");
            String fieldCodes = obj.getString("fieldCodes");
            String deleteFlag = "0";
            String doFieldCodes = "";
            if (obj.containsKey("doFieldCodes")) {
                doFieldCodes = obj.getString("doFieldCodes");
            }
            if (obj.containsKey("deleteData")) {
                deleteFlag = obj.getString("deleteData");
            }
            if (StringUtil.isNotEmpty(tableCode) && StringUtil.isNotEmpty(pkCode) && StringUtil.isNotEmpty(viewPkCode) && "1".equals(deleteFlag)) {
                return metaService.delete(tableCode, ConditionsWrapper.builder().in(pkCode, ArrayUtils.getBeanFieldArray(lists, viewPkCode)));
            }
        }
        return 0;
    }

    @Override
    @Transactional
    public void updateTreePanent4NodeType(String tableCode, String parentId) {
        String pkName = beanService.getPKeyFieldNamesByTableCode(tableCode);
        long count = metaService.countBySql("select count(*) from " + tableCode + " where SY_PARENT={0}", parentId);
        DynaBean one = metaService.selectOneByPk(tableCode, parentId, pkName + ",SY_NODETYPE");
        if (count > 0) {
            if (NodeType.LEAF.equals(one.getStr("SY_NODETYPE"))) {
                one.set(BeanService.KEY_TABLE_CODE, tableCode);
                one.set("SY_NODETYPE", NodeType.GENERAL);
                metaService.update(one);
            }
        } else {
            if (NodeType.GENERAL.equals(one.getStr("SY_NODETYPE"))) {
                one.set(BeanService.KEY_TABLE_CODE, tableCode);
                one.set("SY_NODETYPE", NodeType.LEAF);
                if ("0".equals(one.getStr("SY_DISABLED", "0"))) {
                    metaService.update(one);
                }
            }
        }
    }

    /**
     * list转树形
     *
     * @param lists
     * @param pkCode
     * @param parentCode
     * @return java.util.Map
     */
    @Override
    public Map<String, Object> buildJSONTree4Dyna(List<Map<String, Object>> lists, String pkCode, String parentCode) {
        Map<String, Object> root = new HashMap<>();
        //当前循环这个集合每一个元素
        for (Map<String, Object> node : lists) {
            if (node.get(parentCode) == null || "".equals(node.get(parentCode))) {
                root = node;
                lists.remove(node);
                break;
            }
        }
        createTreeChildren(lists, root, pkCode, parentCode);
        return root;
    }

    @Override
    public List<JSONTreeNode> loadTreeNodeList(String rootId, String tableName, JSONTreeNode template, Query where, List<String> includeIds, String[] beanFields) {
        List<JSONTreeNode> list = new ArrayList<>();
        if (!TreeUtil.verify(template)) {
            return list;
        }

        //创建查询
        ConditionsWrapper select = ConditionsWrapper.builder().table(tableName);
        // 拼接语句
        //(SY_PATH LIKE '%ROOT%' + whereSql )
        select.and(i -> {
            //加入传过来的where条件和预处理参数
            where.buildWrapper(i);
            i.like(template.getNodePath(), rootId);
        });
        // OR ID = 'ROOT'
        select.or().eq(template.getId(), rootId);
        //orderSql
        String orderSql = where.buildOrder();
        if (StringUtils.isBlank(orderSql)) {
            orderSql = " ORDER BY " + template.getParent() + " asc";
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                orderSql += ", " + template.getOrderIndex() + " asc";
            }
            select.apply(orderSql);
        } else {
            select.apply(" ORDER BY ").apply(orderSql);
        }

        //执行查询
        List<Map<String, Object>> treeItems = metaService.selectSql(select);

        //遍历结果构建树形节点对象
        treeItems.forEach(record -> {

            //主键
            String nodeId = (String) record.get(template.getId());
            //排除不在指定节点内的数据
            if (includeIds != null && includeIds.size() > 0 && !includeIds.contains(nodeId)) {
                return;
            }
            JSONTreeNode node = new JSONTreeNode();
            node.setId(nodeId);

            node.setText((String) record.get(template.getText()));
            //编码
            node.setCode((String) record.get(template.getCode()));
            //父节点
            node.setParent((String) record.get(template.getParent()));
            //节点信息
            if (StringUtil.isNotEmpty(template.getNodeInfo())) {
                node.setNodeInfo(StringUtil.getClobValue(record.get(template.getNodeInfo())));
            }
            //节点信息类型
            if (StringUtil.isNotEmpty(template.getNodeInfoType())) {
                node.setNodeInfoType(record.get(template.getNodeInfoType()) + "");
            }
            //是否叶子
            if (StringUtil.isNotEmpty(template.getNodeType())) {
                node.setLeaf(NodeType.LEAF.equalsIgnoreCase(record.get(template.getNodeType()) + ""));
                node.setNodeType(record.get(template.getNodeType()) + "");
            }
            if (StringUtil.isNotEmpty(template.getLayer())) {
                node.setLayer(record.get(template.getLayer()) + "");
            }
            //图标图片地址
            if (StringUtil.isNotEmpty(template.getIcon())) {
                node.setIcon(record.get(template.getIcon()) + "");
            }
            //图标样式
            if (StringUtil.isNotEmpty(template.getIconColor())) {
                node.setIconColor(record.get(template.getIconColor()) + "");
            }
            //是否禁用
            if (StringUtil.isNotEmpty(template.getDisabled())) {
                node.setDisabled(record.get(template.getDisabled()) + "");
            } else {
                node.setDisabled("0");
            }
            //树形路径
            if (StringUtil.isNotEmpty(template.getNodePath())) {
                node.setNodePath(record.get(template.getNodePath()) + "");
            }
            //描述
            if (StringUtil.isNotEmpty(template.getDescription())) {
                node.setDescription(StringUtil.getClobValue(record.get(template.getDescription())));
            }
            //排序
            if (StringUtil.isNotEmpty(template.getOrderIndex())) {
                node.setOrderIndex(record.get(template.getOrderIndex()) + "");
            }
            if (StringUtil.isNotEmpty(template.getTreeOrderIndex())) {
                node.setTreeOrderIndex(record.get(template.getTreeOrderIndex()) + "");
            }

            //保留指定字段
            if (beanFields != null && beanFields.length > 0) {
                List<String> fieldList = Arrays.asList(beanFields);
                Set<String> keySet = record.keySet();
                for (String key : keySet) {
                    if (!fieldList.contains(key)) {
                        record.remove(key);
                    }
                    ;
                }

            }
            //如果是oracle则单独处理
            if (ConstantVars.STR_ORACLE.equals(JEDatabase.getCurrentDatabase())) {
                record.forEach((key, val) -> {
                    if (val == null) {
                        record.put(key, "");
                    } else if (val instanceof Clob) {
                        record.put(key, StringUtil.getClobValue(record.get(key)));
                    }
                });
            }
            node.setBean(record);
            list.add(node);
        });
        return list;
    }

    @Override
    @Transactional
    public FuncInfo functionConfig(String funcCode) {
        return funInfoRpcService.getFuncInfo(funcCode);
    }

    @Override
    public DynaBean changeDefaultPlan(DynaBean dynaBean, String key1, String key2) {
        DynaBean plan = metaService.selectOneByPk(dynaBean.getTableCode(), dynaBean.getPkValue());
        dynaBean.setStr(key2, "1");
        metaService.update(dynaBean);
        List<DynaBean> list = metaService.select(dynaBean.getTableCode(), ConditionsWrapper.builder()
                .eq(key1, plan.getStr(key1))
                .eq(key2, "1")
                .ne(dynaBean.getPkCode(), dynaBean.getPkValue()));
        for (DynaBean item : list) {
            item.setStr(key2, "0");
            metaService.update(item);
        }
        return dynaBean;
    }

    @Override
    public void buildProductInfo(DynaBean dynaBean) {
        if (StringUtil.isNotEmpty(dynaBean.getStr("SY_PRODUCT_ID"))) {
            DynaBean product = metaResourceService.selectOneByPk("JE_PRODUCT_MANAGE", dynaBean.getStr("SY_PRODUCT_ID"));
            if (product != null) {
                dynaBean.setStr("SY_PRODUCT_NAME", product.getStr("PRODUCT_NAME"));
                dynaBean.setStr("SY_PRODUCT_CODE", product.getStr("PRODUCT_CODE"));
            }
        }
    }

    @Override
    public void deleteByFileKeys(List<String> fileKeys, String userId) {
        taskExecutor.execute(() -> {
            //删除文件
            documentInternalRpcService.deleteByFileKeys(fileKeys, userId);
        });
    }

    @Override
    public void updateDictionaryItemNameById(String id, String name, String tableCode, String nameCode, String idCode, String pkCode) {
        List<DynaBean> items = metaService.select(tableCode, ConditionsWrapper.builder().like(idCode, id),
                String.format("%s,%s,%s,%s", tableCode, nameCode, idCode, pkCode));
        String updateSqlTemplate = " UPDATE %s  SET  %s='%s'  WHERE  %s='%s' ";
        List<String> onceItemIdList = new ArrayList<>();

        for (DynaBean item : items) {
            String itemId = item.getStr(idCode);
            String itemName = item.getStr(nameCode);

            if (itemId.equals(id)) {
                onceItemIdList.add("'" + item.getStr(pkCode) + "'");
            } else {
                List<String> itemIdList = Arrays.asList(itemId.split(","));
                List<String> itemNameList = new ArrayList<>(Arrays.asList(itemName.split(",")));
                int itemIdPosition = itemIdList.indexOf(id);
                if (itemIdPosition != -1) {
                    itemNameList.set(itemIdPosition, name);
                    String updateSql = String.format(updateSqlTemplate, tableCode, nameCode, String.join(",", itemNameList), pkCode, item.getStr(pkCode));
                    metaService.executeSql(updateSql);
                }
            }
        }

        if (!onceItemIdList.isEmpty()) {
            String onceItemIdString = String.join(",", onceItemIdList);
            String onceUpdateSql = String.format("UPDATE %s SET %s='%s'  WHERE %s IN (%s)", tableCode, nameCode, name, pkCode, onceItemIdString);
            metaService.executeSql(onceUpdateSql);
        }
    }

}
